#include "Socket.hpp"
#include "Log.hpp"
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <fstream>
#include <vector>
#include <sstream>
#include <unordered_map>
#include "Init.hpp"

const std::string webroot = "./Webroot"; // web根目录
const std::string blank_space_sep = " "; //   空格分隔符
const std::string protocol_sep = "\r\n"; //   协议分隔符
const std::string homepage = "/index.html";

Log lg;
Init it;

class ThreadData
{
public:
    ThreadData(int sock) : sockfd(sock)
    {
    }

public:
    int sockfd;
};

class HttpRequest
{
public:
    // 分割http请求报文  “method url http/version\r\n”
    bool Deserialize(std::string package)
    {
        while (true)
        {
            auto pos = package.find(protocol_sep);
            if (pos == std::string::npos)
                return false;
            std::string temp = package.substr(0, pos);
            if (temp.empty())
                break;
            request_.push_back(temp);
            package.erase(0, pos + protocol_sep.size());
        }
        text_ = package; // 表单使用post方法时，获取传入的参数
        return true;
    }

    // 分割请求行  “method url http/version\r\n”
    void parse()
    {
        std::stringstream ss(request_[0]);
        ss >> method_ >> url_ >> http_version_;

        if (url_ == "/" || url_ == "/index.html")
        {
            web_path += homepage;
        }
        else
        {

            auto pos = url_.find("?");
            if (pos != std::string::npos)
            {
                url_.erase(pos);
            }
            web_path += url_;
        }

        // 确定后缀
        auto pos = url_.find(".");
        if (pos == std::string::npos)
            suffix = "html";
        else
            suffix = url_.substr(pos);
    }

    void DebugPrint()
    {
        for (auto &line : request_)
        {
            // std::cout << "--------------------------------" << std::endl;
            std::cout << line << "\n";
        }

        std::cout << "method: " << method_ << std::endl;
        std::cout << "url: " << url_ << std::endl;
        std::cout << "http_version: " << http_version_ << std::endl;
        std::cout << "file_path: " << web_path << std::endl;
        std::cout << text_ << std::endl;
    }

public:
    std::vector<std::string> request_;

    std::string http_version_; // http版本
    std::string url_;
    std::string method_; // 方法
    std::string text_;   // 正文

    std::string web_path = webroot; // 响应报文中文本所在的文件路径
    std::string suffix;             // 后缀
};

std::string ReadHtml(const std::string &htmlpath)
{
    // if (htmlpath.find("favicon.ico"))
    //     return "";

    std::ifstream in(htmlpath, std::ios::binary);
    if (!in.is_open())
        return "";

    in.seekg(0, std::ios_base::end);
    auto len = in.tellg();
    in.seekg(0, std::ios_base::beg);

    std::string content;
    content.resize(len);

    in.read((char *)content.c_str(), content.size());
    // std::string content;
    // std::string line;
    // while(std::getline(in, line))
    //{
    //     content += line;
    // }

    in.close();

    return content;
}

std::string SuffixToFind(const std::string &suffix)
{
    auto pos = it.contenttype_.find(suffix);
    if (pos == it.contenttype_.end())
        return it.contenttype_[".html"];
    return it.contenttype_[suffix];
}

void HttpHelper(int sockfd)
{
    char buffer[2000];
    // 接收请求报文
    ssize_t n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
    if (n > 0)
    {
        buffer[n] = 0;
        // std::cout << "---------------------------" << std::endl;
        // std::cout << buffer;

        HttpRequest resp;
        resp.Deserialize(buffer);
        resp.parse();
        resp.DebugPrint();

        // 构建响应报文
        std::string text;
        bool ok = true;
        text = ReadHtml(resp.web_path);
        if (text.empty())
        {
            ok = false;
            std::string err_html = webroot;
            err_html += "/";
            err_html += "error.html";
            text = ReadHtml(err_html);
        }

        // //"favicon.ico"
        // if (text == "default")
        // {
        //     return ;
        //     // pthread_cancel(pthread_self());
        // }

        // std::cout << text << std::endl;

        std::string status_line;
        if (ok)
            status_line = "HTTP/1.0 200 OK\r\n";
        else
            status_line = "HTTP/1.0 404 Not Found\r\n";

        std::string response_header = "Content Length:";
        response_header += std::to_string(text.size());
        response_header += "\r\n";
        response_header += "Content-Type:";
        response_header += SuffixToFind(resp.suffix);
        response_header += "\r\n";

        std::string response = status_line;
        response += response_header;
        response += protocol_sep; // 空行
        response += text;
        // std::cout<<text<<std::endl;

        send(sockfd, response.c_str(), response.size(), 0);
        // std::cout << response << std::endl;
    }
}

class HttpServer
{
public:
    HttpServer(const uint16_t port) : port_(port)
    {
    }

    ~HttpServer()
    {
    }

public:
    void start()
    {
        sock_.Socket();
        sock_.Bind(port_);
        sock_.Listen();

        for (;;)
        {
            uint16_t clientport;
            std::string clientip;
            int sockfd = sock_.Accept(&clientip, &clientport);
            if (sockfd < 0)
                continue;

            pthread_t pid;
            ThreadData *td = new ThreadData(sockfd);
            pthread_create(&pid, nullptr, ThreadRun, td);
        }
    }

    static void *ThreadRun(void *args)
    {
        pthread_detach(pthread_self());
        ThreadData *td = static_cast<ThreadData *>(args);

        // 接收请求报文 并发送响应报文
        HttpHelper(td->sockfd);

        close(td->sockfd);
        delete td;

        return nullptr;
    }

private:
    std::uint16_t port_;
    Sock sock_;
};